Imports GoldParser

Public Interface IParser
    Function Parse(ByVal CommandText As String, ByVal grammar As Object) As Parser.SyntaxNode
End Interface
Public Class Parser
    Implements IParser

    Public Function Parse(ByVal CommandText As String, ByVal grammar As Object) As SyntaxNode Implements IParser.Parse

        If Not TypeOf (grammar) Is GoldParser.Grammar Then
            Throw New NotSupportedException("Grammar must be of type GoldParser.Grammar!")
        End If

        Dim reader As New IO.StringReader(CommandText)
        Dim reductionNumber As Integer = 0
        Dim parser As New GoldParser.Parser(reader, grammar)
        parser.TrimReductions = True

        Do While True
            Dim response As ParseMessage = parser.Parse()
            Select Case response
                Case ParseMessage.LexicalError
                    'AddParseAction(parser, response, "Cannot Recognize Token", 
                    '	"",	parser.TokenText, "");
                    Return Nothing

                Case ParseMessage.SyntaxError
                    Dim expectedTokens As System.Text.StringBuilder = New System.Text.StringBuilder()
                    For Each token As Symbol In parser.GetExpectedTokens()
                        expectedTokens.Append(token.Name)
                        expectedTokens.Append(" ")
                    Next
                    'AddParseAction(parser, response, "Expecting the following tokens", 
                    '	"",	expectedTokens.ToString(), "");
                    Return Nothing

                Case ParseMessage.Reduction
                    Dim nonTerminal As New NonTerminalNode(parser.ReductionRule)
                    nonTerminal.ReductionNumber = ++reductionNumber
                    parser.TokenSyntaxNode = nonTerminal
                    Dim childReductionList As New System.Text.StringBuilder()
                    For i As Integer = 0 To parser.ReductionCount - 1
                        Dim node As SyntaxNode = CType(parser.GetReductionSyntaxNode(i), SyntaxNode)
                        nonTerminal.Add(node)
                        'Dim childNode As NonTerminalNode = CType(node, NonTerminalNode)
                        'If childNode IsNot Nothing Then
                        '    childReductionList.Append("#")
                        '    childReductionList.Append(childNode.ReductionNumber)
                        '    childReductionList.Append(" ")
                        'End If
                    Next
                    'AddParseAction(parser, response, nonTerminal.Rule.ToString(),
                    '	reductionNumber.ToString(),
                    '	childReductionList.ToString(),
                    '	nonTerminal.Rule.Index.ToString());
                    Exit Select

                Case ParseMessage.Accept '//=== Success!
                    'AddParseAction(parser, response, parser.ReductionRule.ToString(),	
                    '	"", "", "");
                    Return CType(parser.TokenSyntaxNode, SyntaxNode)
                Case ParseMessage.TokenRead
                    Dim terminal As New TerminalNode(parser.TokenText, parser.TokenString, parser.TokenLineNumber, parser.TokenLinePosition)
                    parser.TokenSyntaxNode = terminal
                    Exit Select

                Case ParseMessage.InternalError
                    'AddParseAction(parser, response, "Error in LR state engine", 
                    '	"",	"", "");
                    Return Nothing
                Case ParseMessage.NotLoadedError
                    '=== Due to the if-statement above, this case statement should never be true
                    'AddParseAction(parser, response, "Compiled Grammar Table not loaded", 
                    '	"",	"", "");
                    'return null;
                    Return Nothing
                Case ParseMessage.CommentError
                    'AddParseAction(parser, response, "Unexpected end of file", 
                    '	"",	"", "");
                    Return Nothing
            End Select
        Loop
        Return Nothing
    End Function

    Public Class SyntaxNode

    End Class
    Public Class TerminalNode
        Inherits SyntaxNode

        'Private _Symbol As Symbol
        Private _text As String
        Private _PrintText As String
        Private _LineNumber As Integer
        Private _LinePosition As Integer

        Public Sub New(ByVal text As String, ByVal printtext As String, ByVal lineNumber As Integer, ByVal linePosition As Integer)
            '   _Symbol = symbol
            _text = text
            _PrintText = printtext
            _LineNumber = lineNumber
            _LinePosition = linePosition
        End Sub
        'Public ReadOnly Property Symbol() As Symbol
        '    Get
        '        Return _Symbol
        '    End Get
        'End Property

        Public ReadOnly Property Text() As String
            Get
                Return _text
            End Get
        End Property

        Public ReadOnly Property LineNumber() As Integer
            Get
                Return _LineNumber
            End Get
        End Property
        Public ReadOnly Property LinePosition()
            Get
                Return _LinePosition
            End Get
        End Property

    End Class
    Public Class NonTerminalNode
        Inherits SyntaxNode

        Private _reductionNumber As Integer
        Private _Rule As GoldParser.Rule
        Private _array As New ArrayList

        Public Sub New(ByVal rule As GoldParser.Rule)
            _Rule = rule
        End Sub

        Public Property ReductionNumber() As Integer
            Get
                Return _reductionNumber
            End Get
            Set(ByVal value As Integer)
                _reductionNumber = value
            End Set
        End Property
        Public ReadOnly Property Count() As Integer
            Get
                Return _array.Count
            End Get
        End Property

        Default Public ReadOnly Property Item(ByVal idx As Integer) As SyntaxNode
            Get
                Return CType(_array(idx), SyntaxNode)
            End Get
        End Property

        Public Sub Add(ByVal node As SyntaxNode)
            _array.Add(node)
        End Sub

        Public ReadOnly Property RuleName() As String
            Get
                Return _Rule.Name
            End Get
        End Property
    End Class
End Class
